﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization.Json;
using System.IO;

/// <summary>
/// Summary description for Class1
/// </summary>
public class Class1
{
	public Class1()
	{
		//
		// TODO: Add constructor logic here
		//
	}
}

public class JSONMethodAttribute : System.Attribute
{
    public JSONMethodAttribute()
    {
    }
}

public class EnhancedWebService : System.Web.Services.WebService
    {
        public EnhancedWebService()
            : base()
        {
            string ServiceMethodName = GetMethodName();
            bool IsJSON = Context.Request.QueryString["form"] == "json";
            if (IsJSON) InterceptJSONMethodRequest(ServiceMethodName);
        }
        private string GetMethodName()
        {
            return Context.Request.Url.Segments[Context.Request.Url.Segments.Length - 1];
        } 
        private void InterceptJSONMethodRequest(string ServiceMethodName)
        { 
            JSONMethodAttribute JMA = GetMethodJSONMethodAttribute(ServiceMethodName);
            if (JMA == null)
            {
                Context.Response.Write("throw new Exception('The Web Service method " + 
                                       ServiceMethodName + " is not available " + 
                                       "as a JSON function. For more " + 
                                       "information contact " + 
                                       "the Web Service Administrators.');");
            }
            else
            { 
                //ToDo: deserialize parameters, call target method, 
                //      deserialize and write return value
            }
            Context.Response.Flush();
            Context.Response.End();
        } 
        private JSONMethodAttribute GetMethodJSONMethodAttribute(string WebServiceMethodName)
        {
            MethodInfo ActiveMethod = this.GetType().GetMethod(WebServiceMethodName);
            JSONMethodAttribute JMA = null;
            if (ActiveMethod != null)
            {
                object[] Attributes = ActiveMethod.GetCustomAttributes(true);
                foreach (object Attribute in Attributes)
                {
                    if (Attribute.GetType() == typeof(JSONMethodAttribute))
                    {
                        JMA = (JSONMethodAttribute)Attribute;
                    }
                }
            }
            else
            {
                Type Service = this.GetType();
                MethodInfo JSONMethod = Service.GetMethod(WebServiceMethodName);
                if (JSONMethod == null) return null;
                ParameterInfo[] JSONMethodParameters = JSONMethod.GetParameters();
                object[] CallParameters = new object[JSONMethodParameters.Length];
                for (int i = 0; i < JSONMethodParameters.Length; i++)
                {
                    ParameterInfo TargetParameter = JSONMethodParameters[i];
                    string RawParameter = Context.Request.Form[TargetParameter.Name];
                    if (RawParameter == null || RawParameter == "")
                        RawParameter = Context.Request.QueryString[TargetParameter.Name];
                    if (RawParameter == null || RawParameter == "")
                        throw new Exception("Missing parameter " + TargetParameter.Name + ".");
                    CallParameters[i] = JSONDeserialize(RawParameter, TargetParameter.ParameterType);
                }
                object JSONMethodReturnValue = JSONMethod.Invoke(this, CallParameters);
                string SerializedReturnValue = JSONSerialize(JSONMethodReturnValue);
                Context.Response.Write(SerializedReturnValue);
            }
            return JMA;
        }
        private string JSONSerialize(object SerializationTarget)
        {
            DataContractJsonSerializer serializer = 
              new DataContractJsonSerializer(SerializationTarget.GetType());
            MemoryStream ms = new MemoryStream();
            serializer.WriteObject(ms, SerializationTarget);
            string Product = Encoding.Default.GetString(ms.ToArray());
            ms.Close();
            return Product;
        }
        private object JSONDeserialize(string DeserializationTarget, Type TargetType)
        {
            MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(DeserializationTarget));
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(TargetType);
            object Product = serializer.ReadObject(ms);
            ms.Close();
            return Product;
        }
    }



